package com.sharp.core.raytrace;

import com.sharp.core.math.Vec3;
import com.sharp.core.math.Vectors3D;
import com.sharp.core.math.primitives.Object3D;
import com.sharp.core.math.primitives.Primitive;

public class Ray {
	int screenX, screenY;
	Vec3 origin, dir;

	
	/////////////////////////////////
	Vec3 rayT;					// origin + t*dir;
	float t;
	
	public static Ray reflectRay(Intersection inter, Ray ray, Primitive p) {
		Ray refRay = new Ray();
		
		
		Vec3 normal = p.normal(ray.getIntersectionVector(inter.getDistance()));
		float cos = Vectors3D.dotProduct(ray.getDir(), normal);
		Vec3 ref = new Vec3(normal).multiply(cos).multiply(2);
		ref.setTo(ref, ray.getDir());
		
		refRay.setOrigin(inter.getPos());
		refRay.setDir(ref);
		refRay.setScreenX(ray.getScreenX());
		refRay.setScreenY(ray.getScreenY());
		return refRay;
	}
	
	public Ray() {
		this.origin = new Vec3();
		this.dir = new Vec3();
		
		this.rayT = new Vec3();
	}

	
	public Ray(Vec3 origin, Vec3 dir) {
		setTo(origin, dir);
	}

	public Ray(Object3D from, Object3D to) {
		this.origin = new Vec3(from.getPos());
		this.dir = new Vec3(from, to);
		this.dir.normalize();
		this.rayT = new Vec3();
	}
	
	public Ray(Vec3 pos, Vec3 dir2, int x, int y) {
		this(pos, dir2);
		this.setTo(pos, dir, x, y);
	}
	
	public Ray(Ray ray, float delta) {
		this.dir = ray.dir;
		this.origin = new Vec3(ray.dir).multiply(delta).add(ray.origin);
	}

	public void setTo(Vec3 pos, Vec3 dir, int x, int y) {
		setTo(pos, dir);
		screenX = x;
		screenY = y;
	}
	
	public void setTo(Vec3 origin, Vec3 dir) {
		this.origin = origin;
		this.dir = dir;
		
		
		this.rayT = new Vec3();
	}
	

	@Override
	public String toString() {
		return "O: "+origin + ", Dir: " + dir; 
	}

	public int getScreenX() {
		return screenX;
	}

	public void setScreenX(int screenX) {
		this.screenX = screenX;
	}

	public int getScreenY() {
		return screenY;
	}

	public void setScreenY(int screenY) {
		this.screenY = screenY;
	}

	public Vec3 getOrigin() {
		return origin;
	}

	public void setOrigin(Vec3 origin) {
		this.origin = origin;
	}

	public Vec3 getDir() {
		return dir;
	}

	public void setDir(Vec3 dir) {
		this.dir = dir;
	}

	public void setTo(Intersection from) {
		this.origin.setTo(from.getPos());
	}
	
	public void setTo(Object3D from, Object3D to) {
		this.origin.setTo(from.getPos());
		this.dir.setTo(from.getPos(), to.getPos());
		this.dir.normalize();
	}
	
	public void setT(float t) {
		this.t = t;
	}
	
	public float getT() {
		return this.t;
	}

	public Vec3 getIntersectionVector(float t) {
		rayT.setTo(dir);
		rayT.multiply(t);
		rayT.add(origin);
		return rayT;
	}
}
